package cmd

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"testing"

	config "code.alibaba-inc.com/agit/quarantine-helper/config"
	"github.com/stretchr/testify/assert"
)

func TestDisplayOneCommit(t *testing.T) {
	config.CommitInfo.ID = true
	config.CommitInfo.Message = true
	config.CommitInfo.CommittedTime = true
	config.CommitInfo.CommitterName = true
	config.CommitInfo.CommitterEmail = true
	config.CommitInfo.AuthoredTime = true
	config.CommitInfo.AuthorName = true
	config.CommitInfo.AuthorEmail = true
	var (
		assert = assert.New(t)
	)
	type testCase struct {
		commitID     string
		detailedInfo string
	}

	testCases := []testCase{
		testCase{
			commitID: "f900c806ce8b8f81ca6c8430becf45db7f95bce2",
			detailedInfo: "-088084-f900c806ce8b8f81ca6c8430becf45db7f95bce2-088084-add a useless file to commit the empty directory\n\n" +
				"Signed-off-by: pengfei <julien.zpf@alibaba-inc.com>\n" +
				"-088084-pengfei-088084-julien.zpf@alibaba-inc.com-088084-2020-02-07T22:02:59+08:00-088084-" +
				"pengfei-088084-julien.zpf@alibaba-inc.com-088084-2020-02-07T22:02:59+08:00-088084-",
		},
		testCase{
			commitID: "80a2f37413841e3a1989e59eda342f4bcc19a880",
			detailedInfo: "-088084-80a2f37413841e3a1989e59eda342f4bcc19a880-088084-do not print redundant newln\n\n" +
				"Signed-off-by: pengfei <julien.zpf@alibaba-inc.com>\n" +
				"-088084-pengfei-088084-julien.zpf@alibaba-inc.com-088084-2020-02-09T16:10:32+08:00-088084-" +
				"pengfei-088084-julien.zpf@alibaba-inc.com-088084-2020-02-09T16:10:32+08:00-088084-",
		},
	}

	repoPath := "/tmp/quarantine-helper.git"
	defer func(dir string) {
		os.RemoveAll(dir)
	}(repoPath)
	cmdArgs := []string{
		"git",
		"clone",
		"--bare",
		"http://gitlab.alibaba-inc.com/agit/quarantine-helper.git",
		repoPath,
	}
	cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
	err := cmd.Run()
	assert.Nil(err)

	for _, testCase := range testCases {
		stdout := os.Stdout
		reader, writer, _ := os.Pipe()
		os.Stdout = writer

		err := displayOneCommit(testCase.commitID)
		assert.Nil(err)
		writer.Close()

		rawOutput, err := ioutil.ReadAll(reader)
		output := strings.TrimSuffix(string(rawOutput), "\n")
		os.Stdout = stdout

		assert.Equal(testCase.detailedInfo, output)
	}
}

func TestDisplayCommits(t *testing.T) {
	input := []string{
		"f900c806ce8b8f81ca6c8430becf45db7f95bce2",
		"80a2f37413841e3a1989e59eda342f4bcc19a880",
	}

	expected := "-088084-f900c806ce8b8f81ca6c8430becf45db7f95bce2-088084-add a useless file to commit the empty directory\n\n" +
		"Signed-off-by: pengfei <julien.zpf@alibaba-inc.com>\n" +
		"-088084-pengfei-088084-julien.zpf@alibaba-inc.com-088084-2020-02-07T22:02:59+08:00-088084-" +
		"pengfei-088084-julien.zpf@alibaba-inc.com-088084-2020-02-07T22:02:59+08:00-088084-" +
		"-088084-80a2f37413841e3a1989e59eda342f4bcc19a880-088084-do not print redundant newln\n\n" +
		"Signed-off-by: pengfei <julien.zpf@alibaba-inc.com>\n" +
		"-088084-pengfei-088084-julien.zpf@alibaba-inc.com-088084-2020-02-09T16:10:32+08:00-088084-" +
		"pengfei-088084-julien.zpf@alibaba-inc.com-088084-2020-02-09T16:10:32+08:00-088084-"

	config.CommitInfo.ID = true
	config.CommitInfo.Message = true
	config.CommitInfo.CommittedTime = true
	config.CommitInfo.CommitterName = true
	config.CommitInfo.CommitterEmail = true
	config.CommitInfo.AuthoredTime = true
	config.CommitInfo.AuthorName = true
	config.CommitInfo.AuthorEmail = true
	var (
		assert = assert.New(t)
	)

	repoPath := "/tmp/quarantine-helper.git"
	defer func(dir string) {
		os.RemoveAll(dir)
	}(repoPath)
	cmdArgs := []string{
		"git",
		"clone",
		"--bare",
		"http://gitlab.alibaba-inc.com/agit/quarantine-helper.git",
		repoPath,
	}
	cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
	env := os.Environ()
	if os.Getenv(GitConfigParameters) != "" {
		env = append(env, fmt.Sprintf("%s=%s", GitConfigParameters, os.Getenv(GitConfigParameters)))
	}
	cmd.Env = env
	err := cmd.Run()
	assert.Nil(err)
	config.Repository = repoPath

	stdout := os.Stdout
	reader, writer, _ := os.Pipe()
	os.Stdout = writer

	err = dispalyCommits(input)
	assert.Nil(err)
	writer.Close()

	rawOutput, err := ioutil.ReadAll(reader)
	output := strings.TrimSuffix(string(rawOutput), "\n")
	os.Stdout = stdout

	assert.Equal(expected, output)

}

func TestDisplayEncryptedCommits(t *testing.T) {
	var (
		assert = assert.New(t)
	)
	err := os.Setenv(GitConfigParameters, "'agit.crypto.enabled=true' 'agit.crypto.secret=nekot-terces'")
	assert.Nil(err)
	TestDisplayCommits(t)
}
